/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#include "sg_local.h"


/*
 ==================
 Light_Think
 ==================
*/
static void Light_Think (entity_t *self){

}

/*
 ==================
 Light_Spawn
 ==================
*/
void Light_Spawn (entity_t *self){

	const char	*material;
	odMat3		axis;
	odVec3		color;
	odVec3		tmp, points[8];
	int			i;

	self->state.type = ET_LIGHT;

	// Get the origin and center
	self->spawnDict.GetVec3("origin", self->state.origin);
	self->spawnDict.GetVec3("center", self->state.center);

	// Get the axis, either as a matrix or as angles
	if (self->spawnDict.GetMat3("rotation", axis))
		self->state.angles = axis.ToAngles();
	else {
		if (self->spawnDict.GetAngles("angles", self->state.angles))
			self->state.angles.Normalize360();
		else {
			self->spawnDict.GetFloat("angle", &self->state.angles[1]);

			self->state.angles[0] = 0.0f;
			self->state.angles[1] = AngleMod(self->state.angles[1]);
			self->state.angles[2] = 0.0f;
		}

		axis = self->state.angles.ToMat3();
	}

	// Get the radius, FOV, and falloff range
	self->spawnDict.GetVec3("radius", self->state.radius, "1000 1000 1000");
	self->state.radius.Clamp(1.0f, M_INFINITY);

	self->spawnDict.GetFloat("fovX", &self->state.fovX, "90");
	self->state.fovX = M_ClampFloat(self->state.fovX, 1.0f, 179.0f);

	self->spawnDict.GetFloat("fovY", &self->state.fovY, "90");
	self->state.fovY = M_ClampFloat(self->state.fovY, 1.0f, 179.0f);

	self->spawnDict.GetFloat("falloffRange", &self->state.falloffRange, "200");
	self->state.falloffRange = M_ClampFloat(self->state.falloffRange, 1.0f, M_INFINITY);

	// Get the attributes
	self->spawnDict.GetBool("projected", &self->state.projected);
	self->spawnDict.GetBool("parallel", &self->state.parallel);

	if (self->state.parallel && self->state.center.IsCleared())
		self->state.center.Set(1.0f, -1.0f, 1.0f);

	self->spawnDict.GetBool("noShadows", &self->state.noShadows);

	self->spawnDict.GetInteger("detailLevel", &self->state.detailLevel);
	self->state.detailLevel = M_ClampLong(self->state.detailLevel, 0, 2);

	// Get the material
	if (self->state.projected)
		self->spawnDict.GetString("material", &material, "_defaultProjectedLight");
	else
		self->spawnDict.GetString("material", &material, "_defaultPointLight");

	self->state.materialIndex = SG_MaterialLightIndex(material);

	// Get the color
	self->spawnDict.GetVec3("color", color, "1 1 1");

	self->state.materialParms[MATERIALPARM_RED] = color[0];
	self->state.materialParms[MATERIALPARM_GREEN] = color[1];
	self->state.materialParms[MATERIALPARM_BLUE] = color[2];

	// Get the material parms.
	// Note that MATERIALPARM_ALPHA and MATERIALPARM_MISC have a special
	// meaning for fog lights.
	self->spawnDict.GetFloat("materialParm3", &self->state.materialParms[MATERIALPARM_ALPHA], "1");

	if (!self->spawnDict.GetFloat("materialParm4", &self->state.materialParms[MATERIALPARM_TIMEOFFSET]))
		self->state.materialParms[MATERIALPARM_TIMEOFFSET] = -MS2SEC(level.time);

	self->spawnDict.GetFloat("materialParm5", &self->state.materialParms[MATERIALPARM_DIVERSITY]);
	self->spawnDict.GetFloat("materialParm6", &self->state.materialParms[MATERIALPARM_MISC], "1");
	self->spawnDict.GetFloat("materialParm7", &self->state.materialParms[MATERIALPARM_MODE]);


	// TODO!!!


	// See if it starts off (must be triggered to turn on)


	// See if it plays a sound


	// If health is specified, the light is breakable (it must specify a model)
	self->spawnDict.GetInteger("health", &self->health);
	if (self->health){

		// See if it has targets to trigger when broken (ie: to change model,
		// sound, color, etc, turn off a flare, etc)

	}

	// Set the callback functions
	self->Think = Light_Think;

	// Link the entity
	self->origin = self->state.origin;
	self->angles = self->state.angles;
	self->axis = axis;

	// TODO!!!
	if (self->state.projected)
		self->bounds.Set(-self->state.falloffRange, self->state.falloffRange);
	else {
		// Compute the corner points
		for (i = 0; i < 8; i++){
			tmp[0] = (i & 1) ? -self->state.radius[0] : self->state.radius[0];
			tmp[1] = (i & 2) ? -self->state.radius[1] : self->state.radius[1];
			tmp[2] = (i & 4) ? -self->state.radius[2] : self->state.radius[2];

			// Transform into world space
			axis.UnprojectVector(tmp, points[i]);
		}

		self->bounds.FromPoints(points);
	}

	SG_LinkEntity(self);
}

